// 验证码
// 参考：https://blog.csdn.net/y1391625461/article/details/125408139
// 参考：https://captcha.mojotv.cn/

package captcha

import (
	"context"

	"gitee.com/copylian/lian-go.git/constant"
	"github.com/mojocn/base64Captcha"
)

// configJsonBody 请求结构体
type configJsonBody struct {
	Id            string
	CaptchaType   string
	VerifyValue   string
	DriverAudio   *base64Captcha.DriverAudio
	DriverString  *base64Captcha.DriverString
	DriverChinese *base64Captcha.DriverChinese
	DriverMath    *base64Captcha.DriverMath
	DriverDigit   *base64Captcha.DriverDigit
}

// 默认store
var store = base64Captcha.DefaultMemStore

// 默认driver
var driver base64Captcha.Driver

// Generate 生成验证码
// 格式：captchaHelper.Generate(ctx, map[string]string{"type": "digit", "store": "redis", "storeDbName": "default", "width":240, "height":80, "length":6})
// 验证码类型type：audio-语音、string-字符串、math-数学、chinese-中文、digit-数字
// 存储store：redis，默认是 base64Captcha.DefaultMemStore
// 存储storeDbName：连接的存储库，如redis连接redis.yaml文件中的default配置
//
//	id, b64s, cErr := captchaHelper.Generate(c.GCtx, map[string]interface{}{
//		"type":        "digit",                // audio-语音、string-字符串、math-数学、chinese-中文、digit-数字，不存在或者空着默认digit
//		"store":       "redis",                // redis存储，不存在或者空着默认使用base64Captcha.DefaultMemStore
//		"storeDbName": "default",              // redis连接实例
//		"width":       constant.CaptchaWidth,  // 宽度，不存在或者空着默认240
//		"height":      constant.CaptchaHeight, // 高度，不存在或者空着默认80
//		"length":      constant.CaptchaLength, // 长度，不存在或者空着默认6
//	})
func Generate(ctx context.Context, captchaInfo map[string]interface{}) (id, b64s string, err error) {
	// 获取driver
	driver = GetDriver(captchaInfo)

	// 获取store
	store := GetStore(ctx, captchaInfo)

	// 生成验证码
	c := base64Captcha.NewCaptcha(driver, store)
	id, b64s, err = c.Generate()
	return id, b64s, err
}

// Verify 验证验证码是否正确
// 格式：captchaHelper.Verify(ctx, map[string]string{"store": "redis", "storeDbName": "default"})
// 存储store：redis，默认是 base64Captcha.DefaultMemStore
// 存储storeDbName：连接的存储库，如redis连接redis.yaml文件中的default配置
//
//	res := captchaHelper.Verify(c.GCtx, captchaId, Captcha, map[string]interface{}{
//		"store":       "redis",   // redis存储，不存在或者空着默认使用base64Captcha.DefaultMemStore
//		"storeDbName": "default", // redis连接实例
//	})
func Verify(ctx context.Context, id, value string, captchaInfo map[string]interface{}) bool {
	// 获取参数
	param := configJsonBody{
		Id:          id,
		VerifyValue: value,
	}

	// 创建store
	store := GetStore(ctx, captchaInfo)
	return store.Verify(param.Id, param.VerifyValue, true)
}

// GetDriver 获取driver
func GetDriver(captchaInfo map[string]interface{}) base64Captcha.Driver {

	// 类型
	var captchaType string
	if val, ok := captchaInfo["type"].(string); ok && val != "" {
		// 断言
		captchaType = val
	}

	// 判断是否有自定义的参数
	captchaWidth := constant.CaptchaWidth
	if val, ok := captchaInfo["width"].(int); ok && val != 0 {
		// 断言
		captchaWidth = val
	}
	captchaHeight := constant.CaptchaHeight
	if val, ok := captchaInfo["height"].(int); ok && val != 0 {
		// 断言
		captchaHeight = val
	}
	captchaLength := constant.CaptchaLength
	if val, ok := captchaInfo["length"].(int); ok && val != 0 {
		// 断言
		captchaLength = val
	}

	// 获取参数
	param := configJsonBody{
		CaptchaType: captchaType,
		DriverAudio: &base64Captcha.DriverAudio{
			Length:   captchaLength, // 长度
			Language: "zh",          // 语言 "en", "ja", "ru", "zh"
		},
		DriverString: &base64Captcha.DriverString{
			Width:           captchaWidth,                                                          // 宽度
			Height:          captchaHeight,                                                         // 高度
			Length:          captchaLength,                                                         // 长度
			NoiseCount:      constant.CaptchaNoiseCount,                                            // 噪点数
			ShowLineOptions: base64Captcha.OptionShowHollowLine | base64Captcha.OptionShowSineLine, // 显示线条选项 OptionShowHollowLine | OptionShowSlimeLine | OptionShowSineLine
			Source:          constant.CaptchaStringSource,                                          // Source是一个unicode，它是来自的rand字符串
			// BgColor: &color.RGBA{
			// 	R: 40,
			// 	G: 30,
			// 	B: 89,
			// 	A: 29,
			// }, // 背景颜色
			// FontsStorage:    FontsStorage,         // 字体存储字体存储
			// Fonts: []string{"ApothecaryFont.ttf", "RitaSmith.ttf"}, // 按名称加载的字体请参阅fonts.go的评论
			// fontsArray:      []*truetype.Font,
		},
		DriverChinese: &base64Captcha.DriverChinese{
			Width:           captchaWidth,                                                          // 宽度
			Height:          captchaHeight,                                                         // 高度
			Length:          captchaLength,                                                         // 长度
			NoiseCount:      constant.CaptchaNoiseCount,                                            // 噪点数
			ShowLineOptions: base64Captcha.OptionShowHollowLine | base64Captcha.OptionShowSineLine, // 显示线条选项 OptionShowHollowLine | OptionShowSlimeLine | OptionShowSineLine
			Source:          constant.CaptchaChineseSource,                                         // Source是一个unicode，它是来自的rand字符串，可以使用逗号隔开如：如果,生成,财神
			// BgColor: &color.RGBA{
			// 	R: 40,
			// 	G: 30,
			// 	B: 89,
			// 	A: 29,
			// }, // 背景颜色
			// FontsStorage:    FontsStorage,         // 字体存储字体存储
			Fonts: []string{"wqy-microhei.ttc"}, // 按名称加载的字体请参阅fonts.go的评论，这个字体必须支持中文，否则会乱码
			// fontsArray:      []*truetype.Font,
		},
		DriverMath: &base64Captcha.DriverMath{
			Width:           captchaWidth,                                                          // 宽度
			Height:          captchaHeight,                                                         // 高度
			NoiseCount:      constant.CaptchaNoiseCount,                                            // 噪点数
			ShowLineOptions: base64Captcha.OptionShowHollowLine | base64Captcha.OptionShowSineLine, // 显示线条选项 OptionShowHollowLine | OptionShowSlimeLine | OptionShowSineLine
			// BgColor: &color.RGBA{
			// 	R: 40,
			// 	G: 30,
			// 	B: 89,
			// 	A: 29,
			// }, // 背景颜色
			// FontsStorage:    FontsStorage,         // 字体存储字体存储
			// Fonts: []string{"ApothecaryFont.ttf", "RitaSmith.ttf"}, // 按名称加载的字体请参阅fonts.go的评论
			// fontsArray:      []*truetype.Font,
		},
		DriverDigit: &base64Captcha.DriverDigit{
			Width:    captchaWidth,  // 宽度
			Height:   captchaHeight, // 高度
			Length:   captchaLength, // 长度
			MaxSkew:  0.7,           // 歪曲程度
			DotCount: 80,            // 背景圆的数量
		},
	}

	// 判断driver
	switch param.CaptchaType {
	case "audio":
		driver = param.DriverAudio
	case "string":
		driver = param.DriverString.ConvertFonts()
	case "math":
		driver = param.DriverMath.ConvertFonts()
	case "chinese":
		driver = param.DriverChinese.ConvertFonts()
	default:
		driver = param.DriverDigit
	}
	return driver
}

// GetStore 获取存储store
func GetStore(ctx context.Context, captchaInfo map[string]interface{}) base64Captcha.Store {
	// 存储类型
	var captchaStore string
	if val, ok := captchaInfo["store"].(string); ok && val != "" {
		// 断言
		captchaStore = val
	}

	// 判断
	switch captchaStore {
	case "redis":
		// 默认连接实例
		var captchastoreDbName = "default"
		if val, ok := captchaInfo["storeDbName"].(string); ok && val != "" {
			// 断言
			captchastoreDbName = val
		}
		store, _ = NewRedisStore(ctx, captchastoreDbName)
	default:
		store = base64Captcha.DefaultMemStore
	}
	return store
}
